#ifndef RAJA_TTF2_FONT
#define RAJA_TTF2_FONT

#include <boost/shared_ptr.hpp>

#include "../../math/math.hpp"

namespace raja
{
	namespace ttf2
	{
		struct sw_font;
		typedef boost::shared_ptr<sw_font>		sw_font_ptr;

		struct sw_font
		{
			enum
			{
				CHAR_START	= 32,
				CHAR_END = 127,
			};

			static sw_font_ptr create_instance(const std::string &file_name, real32 size,
											bool use_hint = true, bool force_autohinter = false, bool anti_alias = false);

			~sw_font() { /* if( __whole_pixmap_data ) delete[] __whole_pixmap_data; */ }

			real32			get_font_size() const { return __size; }
			bool			is_using_hint() const { return __use_hint; }
			bool			is_forcing_autohinter() const { return __force_autohinter; }
			bool			is_anti_aliased() const { return __anti_alias; }

			void			get_char_bbox(uint8 ch, math::ivec2 &imin, math::ivec2 &imax) const
			{
				imin	= __characters[ch - sw_font::CHAR_START].box_min;
				imax	= __characters[ch - sw_font::CHAR_START].box_max;
			}

			sint32			get_char_width(uint8 ch) const { return __characters[ch - sw_font::CHAR_START].width; }
			sint32			get_char_height(uint8 ch) const { return __characters[ch - sw_font::CHAR_START].height; }

			real32			get_char_advance(uint8 ch) const { return __characters[ch - sw_font::CHAR_START].advance; }

			const uint8*	get_char_pixmap(uint8 ch) const { return &__pixmap[__characters[ch - sw_font::CHAR_START].pixmap_offset]; }

			real32			get_max_char_width() const { return __max_char_width; }
			real32			get_max_char_height() const { return __max_char_height; }

			uint32			get_num_chars() const { return __characters.size(); }

			uint32			get_whole_pixmap_width() const { return __whole_pixmap_width; }
			uint32			get_whole_pixmap_height() const { return __whole_pixmap_height; }

			const uint8*	get_whole_pixmap_data() const { return &(__whole_pixmap_data[0]); }

			// wp is for whole pixmap
			void			get_char_wp_bbox(uint8 ch, math::ivec2 &imin, math::ivec2 &imax) const
			{
				imin	= __characters[ch - sw_font::CHAR_START].src_min;
				imax	= __characters[ch - sw_font::CHAR_START].src_max;
			}

		private:

			/// default constructor: keep this one private
			sw_font() /*: __whole_pixmap_data(0)*/ {}

			struct __character_info
			{
				uint8			char_code;	///< char ASCII code

				math::ivec2	box_min;	///< char bounding box min position
				math::ivec2	box_max;	///< char bounding box max position

				sint32			width;		///< char width
				sint32			height;		///< char height

				real32			advance;	///< number of pixels to add horizontally after this character

				uint32			pixmap_offset;		///< pointer to char pixmap

				math::ivec2	src_min;	///< source texture min coordinates
				math::ivec2	src_max;	///< source texture max coordinates

				__character_info() : char_code(0), box_min(0),
					box_max(0), width(0),
					height(0), advance(0), pixmap_offset(0),
					src_min(0), src_max(0)
				{
				}

				__character_info(sint32 _width, sint32 _height) :
					char_code(0), box_min(0),
					box_max(0), width(_width),
					height(_height), advance(0), pixmap_offset(0),
					src_min(0), src_max(0)
				{
				}

				__character_info(const __character_info &ch_) :
					char_code(ch_.char_code),
					box_min(ch_.box_min), box_max(ch_.box_max), width(ch_.width),
					height(ch_.height), advance(ch_.advance), pixmap_offset(ch_.pixmap_offset),
					src_min(ch_.src_min), src_max(ch_.src_max)
				{
				}

				~__character_info() {}

			};


			real32				__size;		///< height font size in pixels
			bool 				__use_hint;	///< use font hinting
			bool				__force_autohinter;	///< force font auto hinting
			bool				__anti_alias;	///< force anti-alias
			std::vector<uint8>	__pixmap;	///< the pixmap bytes (needs __character_info to decode)
			real32				__max_char_width;	///< maximum character width
			real32				__max_char_height;	///< maximum character height

			std::vector<__character_info>	__characters;	///< the characters

			/// @section whole pixmap
			/// The whole pixmap stores all the glyph in one big pixmap (bitmap or texture)
			/// @note currently only square pixmap generation is supported.

			uint32				__whole_pixmap_width;	///< whole pixmap width
			uint32				__whole_pixmap_height;	///< whole pixmap height
			std::vector<uint8>				__whole_pixmap_data;	///< all the pixels data
		};
	} // namespace ttf2
} // namespace raja
#endif // RAJA_TTF2_FONT
